/**
 * 
 */
package jmd.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Vector;

import jmd.bean.ClientEntity;
import jmd.construct.Construct;
import jmd.parse.Parse;

import org.apache.log4j.Logger;

/**
 * @author Gordon
 * 
 */
public class AyServer extends Thread
{
	// 加入log4j插件显示注释
	private static Logger logger = Logger.getLogger(AyServer.class.getName());

	// 端口号
	private int serverPort;
	// 定义一个选择器
	private Selector serverSelector = null;
	// 读缓冲区
	private ByteBuffer rBuffer = ByteBuffer.allocate(1024);
	// 写缓冲区
	private ByteBuffer wBuffer = ByteBuffer.allocate(1024);
	// 定义一个静态容器装客户信息
	public static Vector<ClientEntity> clients = new Vector<ClientEntity>();

	// 客户端IP
	private String clientIP = "";

	// 声明一个文件io操作对象
	public static DataIO fileIO = new DataIO();
	// 定义一个 构造协议接口
	private Construct constructInterface;
	// 定义一个 解析协议接口
	private Parse parseInterface;

	// 构造函数
	public AyServer(int argPort)
	{
		this.serverPort = argPort;
	}

	// 服务器初始化（从文件初始化容器，初始化接口）
	public void Initial()
	{
		try
		{
			clients = fileIO.getClientVectorData();
		} catch (IOException e1)
		{
			e1.printStackTrace();
		}

		try
		{
			parseInterface = (Parse) Class.forName("jmd.parse.ParseImpl").newInstance();
			constructInterface = (Construct) Class.forName("jmd.construct.ConstructImpl")
					.newInstance();
		} catch (InstantiationException e)
		{
			e.printStackTrace();
		} catch (IllegalAccessException e)
		{
			e.printStackTrace();
		} catch (ClassNotFoundException e)
		{
			e.printStackTrace();
		}
		// 读取文件将对应信息写进clients Vector
	}

	@Override
	public void run()
	{
		Initial();
		try
		{
			ServerSocketChannel mainServerChannel = ServerSocketChannel.open();

			// 配置通到使用非阻塞模式，在非阻塞模式下，可以编写多道程序同时避免使用复杂的多线程
			mainServerChannel.configureBlocking(false);

			serverSelector = Selector.open();

			mainServerChannel.socket().bind(new InetSocketAddress(this.serverPort));

			mainServerChannel.register(serverSelector, SelectionKey.OP_ACCEPT);

			logger.debug("Server Starting.......");

			while (true)
			{
				logger.debug("listening new connection............");

				// 服务器开始监听端口，提供服务
				serverSelector.select();

				// 取得代表端通道的键集合
				Iterator<SelectionKey> it = serverSelector.selectedKeys().iterator();
				while (it.hasNext())
				{
					SelectionKey key = it.next();
					it.remove();
					if (key.isAcceptable())
					{
						SocketChannel newChannel = null;

						ServerSocketChannel newServerChannel = (ServerSocketChannel) key
								.channel();

						newChannel = newServerChannel.accept();
						// 配置和注册代表客户连接的通道对象
						newChannel.configureBlocking(false);

						newChannel.register(serverSelector, SelectionKey.OP_READ);

						clientIP = newChannel.socket().getInetAddress().getHostAddress();
						// 调用匹配函数，返回一个客户实体
						ClientEntity ce = SelectOneEntity(clientIP);
						logger.debug("Client IP :" + clientIP + "  connect success!");

						// 调用构造协议方法，传进一个实体，返回一个buffer
						wBuffer.clear();
						wBuffer = constructInterface.constructProtocol(ce);
						newChannel.write(wBuffer);
						logger.debug("Initial bitmap to Client!");
					}

					if (key.isReadable())
					{
						SocketChannel channel = (SocketChannel) key.channel();

						rBuffer.clear();
						int lengthOfRead = channel.read(rBuffer);
						rBuffer.flip();

						// 解析协议放进容器
						AddClientEntity(parseInterface.decodeProtocol(rBuffer));

						// 写入文件
						WriteFile();

					}
				}
			}
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		AyServer server = new AyServer(1001);
		server.start();

		// //设置主菜单
		// final Object[][] MAIN_MENU = {
		// // mnemonic, description, method
		// {"1", "list  clients", "chooseOneToDelete"},
		// {"2", "disconnect the client", "chooseOneToDelete"},
		// {"Q", "Quit", "quit"}
		//	        
		// };
		//		
		// new CommandServer().doMenu(MAIN_MENU,true);

		// Scanner s = new Scanner(System.in);
		// System.out.println("1、停止服务器");
		// String name = s.nextLine();
		// if (name.equals("1"))
		// {
		// WriteFile();
		// //server.stop();
		// System.exit(0);
		// System.out.println("停止成功！！");
		// } else
		// {
		// System.out.println("输入错误!");
		// }
	}

	/**
	 * 将容器信息写入文件
	 */
	private static void WriteFile()
	{
		try
		{
			fileIO.storeAllData(clients);
		} catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 增加客户到容器
	 * 
	 * @param argContent
	 */
	private void AddClientEntity(String[] argContent)
	{
		boolean isExist = false;
		ClientEntity ce = null;

		for (int i = 0; i < clients.size(); i++)
		{
			if (clients.get(i).getIp().equals(argContent[0]))
			{
				ce = clients.get(i);
				try
				{
					ce.setFileName(argContent[1]);
					ce.setType(Integer.parseInt(argContent[2]));
					ce.setColor(Integer.parseInt(argContent[3]));
					ce.setFillOut(Boolean.parseBoolean(argContent[4]));
				} catch (Exception e)
				{
				}
				isExist = true;
				break;
			}
		}
		if (!isExist)
		{
			ce = new ClientEntity();
			try
			{
				ce.setIp(argContent[0]);
				ce.setFileName(argContent[1]);
				ce.setType(Integer.parseInt(argContent[2]));
				ce.setColor(Integer.parseInt(argContent[3]));
				ce.setFillOut(Boolean.parseBoolean(argContent[4]));
			} catch (Exception e)
			{
			}
			clients.add(ce);
		}

	}

	/**
	 * 查询容器是否存在对应客户
	 * 
	 * @param argIP
	 * @return ClientEntity
	 */
	private ClientEntity SelectOneEntity(String argIP)
	{

		for (int i = 0; i < clients.size(); i++)
		{
			if (clients.get(i).getIp().equals(argIP))
			{
				return clients.get(i);
			}
		}

		return new ClientEntity(clientIP);
	}

}
